home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / gnu / fileutils_3_3.lha / fileutils-3.3 / lib / getdate.c < prev    next >
C/C++ Source or Header  |  1992-08-02  |  45KB  |  1,793 lines

  1.  
  2. /*  A Bison parser, made from getdate.y  */
  3.  
  4. #define    tAGO    258
  5. #define    tDAY    259
  6. #define    tDAYZONE    260
  7. #define    tID    261
  8. #define    tMERIDIAN    262
  9. #define    tMINUTE_UNIT    263
  10. #define    tMONTH    264
  11. #define    tMONTH_UNIT    265
  12. #define    tSEC_UNIT    266
  13. #define    tSNUMBER    267
  14. #define    tUNUMBER    268
  15. #define    tZONE    269
  16. #define    tDST    270
  17.  
  18. #line 1 "getdate.y"
  19.  
  20. /* $Revision: 2.1 $
  21. **
  22. **  Originally written by Steven M. Bellovin <smb@research.att.com> while
  23. **  at the University of North Carolina at Chapel Hill.  Later tweaked by
  24. **  a couple of people on Usenet.  Completely overhauled by Rich $alz
  25. **  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
  26. **  send any email to Rich.
  27. **
  28. **  This grammar has eight shift/reduce conflicts.
  29. **
  30. **  This code is in the public domain and has no copyright.
  31. */
  32. /* SUPPRESS 287 on yaccpar_sccsid *//* Unusd static variable */
  33. /* SUPPRESS 288 on yyerrlab *//* Label unused */
  34.  
  35. #ifdef __GNUC__
  36. #define alloca __builtin_alloca
  37. #else
  38. #ifdef sparc
  39. #include <alloca.h>
  40. #else
  41. #ifdef _AIX /* for Bison */
  42.  #pragma alloca
  43. #else
  44. char *alloca ();
  45. #endif
  46. #endif
  47. #endif
  48.  
  49. #include <stdio.h>
  50. #include <ctype.h>
  51.  
  52. #if    defined(vms)
  53. #include <types.h>
  54. #include <time.h>
  55. #else
  56. #include <sys/types.h>
  57. #if    defined(USG) || !defined(HAVE_FTIME)
  58. /*
  59. **  If you need to do a tzset() call to set the
  60. **  timezone, and don't have ftime().
  61. */
  62. struct timeb {
  63.     time_t        time;        /* Seconds since the epoch    */
  64.     unsigned short    millitm;    /* Field not used        */
  65.     short        timezone;
  66.     short        dstflag;    /* Field not used        */
  67. };
  68. #else
  69. #include <sys/timeb.h>
  70. #endif    /* defined(USG) || defined(FTIME_MISSING) */
  71. #if    defined(BSD4_2) || defined(BSD4_1C)
  72. #include <sys/time.h>
  73. #else
  74. #include <time.h>
  75. #endif    /* defined(BSD4_2) */
  76. #endif    /* defined(vms) */
  77.  
  78. #if defined (STDC_HEADERS) || defined (USG)
  79. #include <string.h>
  80. #endif
  81.  
  82. #if sgi
  83. #undef timezone
  84. #endif
  85.  
  86. extern struct tm    *localtime();
  87.  
  88. #define yyparse getdate_yyparse
  89. #define yylex getdate_yylex
  90. #define yyerror getdate_yyerror
  91.  
  92. #if    !defined(lint) && !defined(SABER)
  93. static char RCS[] =
  94.     "$Header: str2date.y,v 2.1 90/09/06 08:15:06 cronan Exp $";
  95. #endif    /* !defined(lint) && !defined(SABER) */
  96.  
  97.  
  98. #define EPOCH        1970
  99. #define HOUR(x)        ((time_t)(x) * 60)
  100. #define SECSPERDAY    (24L * 60L * 60L)
  101.  
  102.  
  103. /*
  104. **  An entry in the lexical lookup table.
  105. */
  106. typedef struct _TABLE {
  107.     char    *name;
  108.     int        type;
  109.     time_t    value;
  110. } TABLE;
  111.  
  112.  
  113. /*
  114. **  Daylight-savings mode:  on, off, or not yet known.
  115. */
  116. typedef enum _DSTMODE {
  117.     DSTon, DSToff, DSTmaybe
  118. } DSTMODE;
  119.  
  120. /*
  121. **  Meridian:  am, pm, or 24-hour style.
  122. */
  123. typedef enum _MERIDIAN {
  124.     MERam, MERpm, MER24
  125. } MERIDIAN;
  126.  
  127.  
  128. /*
  129. **  Global variables.  We could get rid of most of these by using a good
  130. **  union as the yacc stack.  (This routine was originally written before
  131. **  yacc had the %union construct.)  Maybe someday; right now we only use
  132. **  the %union very rarely.
  133. */
  134. static char    *yyInput;
  135. static DSTMODE    yyDSTmode;
  136. static time_t    yyDayOrdinal;
  137. static time_t    yyDayNumber;
  138. static int    yyHaveDate;
  139. static int    yyHaveDay;
  140. static int    yyHaveRel;
  141. static int    yyHaveTime;
  142. static int    yyHaveZone;
  143. static time_t    yyTimezone;
  144. static time_t    yyDay;
  145. static time_t    yyHour;
  146. static time_t    yyMinutes;
  147. static time_t    yyMonth;
  148. static time_t    yySeconds;
  149. static time_t    yyYear;
  150. static MERIDIAN    yyMeridian;
  151. static time_t    yyRelMonth;
  152. static time_t    yyRelSeconds;
  153.  
  154.  
  155. #line 138 "getdate.y"
  156. typedef union {
  157.     time_t        Number;
  158.     enum _MERIDIAN    Meridian;
  159. } YYSTYPE;
  160.  
  161. #ifndef YYLTYPE
  162. typedef
  163.   struct yyltype
  164.     {
  165.       int timestamp;
  166.       int first_line;
  167.       int first_column;
  168.       int last_line;
  169.       int last_column;
  170.       char *text;
  171.    }
  172.   yyltype;
  173.  
  174. #define YYLTYPE yyltype
  175. #endif
  176.  
  177. #include <stdio.h>
  178.  
  179. #ifndef __STDC__
  180. #define const
  181. #endif
  182.  
  183.  
  184.  
  185. #define    YYFINAL        51
  186. #define    YYFLAG        -32768
  187. #define    YYNTBASE    19
  188.  
  189. #define YYTRANSLATE(x) ((unsigned)(x) <= 270 ? yytranslate[x] : 29)
  190.  
  191. static const char yytranslate[] = {     0,
  192.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  193.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  194.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  195.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  196.      2,     2,     2,    17,     2,     2,    18,     2,     2,     2,
  197.      2,     2,     2,     2,     2,     2,     2,    16,     2,     2,
  198.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  199.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  200.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  201.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  202.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  203.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  204.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  205.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  206.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  207.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  208.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  209.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  210.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  211.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  212.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  213.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  214.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  215.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  216.      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
  217.      2,     2,     2,     2,     2,     1,     2,     3,     4,     5,
  218.      6,     7,     8,     9,    10,    11,    12,    13,    14,    15
  219. };
  220.  
  221. static const short yyprhs[] = {     0,
  222.      0,     1,     4,     6,     8,    10,    12,    14,    16,    19,
  223.     24,    29,    36,    43,    45,    47,    50,    52,    55,    58,
  224.     62,    68,    72,    75,    80,    83,    87,    90,    92,    95,
  225.     98,   100,   103,   106,   108,   111,   114,   116,   118,   119
  226. };
  227.  
  228. static const short yyrhs[] = {-    1,
  229.     19,    20,     0,    21,     0,    22,     0,    24,     0,    23,
  230.      0,    25,     0,    27,     0,    13,     7,     0,    13,    16,
  231.     13,    28,     0,    13,    16,    13,    12,     0,    13,    16,
  232.     13,    16,    13,    28,     0,    13,    16,    13,    16,    13,
  233.     12,     0,    14,     0,     5,     0,    14,    15,     0,     4,
  234.      0,     4,    17,     0,    13,     4,     0,    13,    18,    13,
  235.      0,    13,    18,    13,    18,    13,     0,    13,    12,    12,
  236.      0,     9,    13,     0,     9,    13,    17,    13,     0,    13,
  237.      9,     0,    13,     9,    13,     0,    26,     3,     0,    26,
  238.      0,    13,     8,     0,    12,     8,     0,     8,     0,    12,
  239.     11,     0,    13,    11,     0,    11,     0,    12,    10,     0,
  240.     13,    10,     0,    10,     0,    13,     0,     0,     7,     0
  241. };
  242.  
  243. #if YYDEBUG != 0
  244. static const short yyrline[] = { 0,
  245.    152,   153,   156,   159,   162,   165,   168,   171,   174,   180,
  246.    186,   193,   199,   209,   213,   217,   224,   228,   232,   238,
  247.    242,   247,   253,   257,   262,   266,   273,   277,   280,   283,
  248.    286,   289,   292,   295,   298,   301,   304,   309,   337,   340
  249. };
  250.  
  251. static const char * const yytname[] = {   "$",
  252. "error","$illegal.","tAGO","tDAY","tDAYZONE","tID","tMERIDIAN","tMINUTE_UNIT","tMONTH","tMONTH_UNIT",
  253. "tSEC_UNIT","tSNUMBER","tUNUMBER","tZONE","tDST","':'","','","'/'","spec","item",
  254. "time","zone","day","date","rel","relunit","number","o_merid",""
  255. };
  256. #endif
  257.  
  258. static const short yyr1[] = {     0,
  259.     19,    19,    20,    20,    20,    20,    20,    20,    21,    21,
  260.     21,    21,    21,    22,    22,    22,    23,    23,    23,    24,
  261.     24,    24,    24,    24,    24,    24,    25,    25,    26,    26,
  262.     26,    26,    26,    26,    26,    26,    26,    27,    28,    28
  263. };
  264.  
  265. static const short yyr2[] = {     0,
  266.      0,     2,     1,     1,     1,     1,     1,     1,     2,     4,
  267.      4,     6,     6,     1,     1,     2,     1,     2,     2,     3,
  268.      5,     3,     2,     4,     2,     3,     2,     1,     2,     2,
  269.      1,     2,     2,     1,     2,     2,     1,     1,     0,     1
  270. };
  271.  
  272. static const short yydefact[] = {     1,
  273.      0,    17,    15,    31,     0,    37,    34,     0,    38,    14,
  274.      2,     3,     4,     6,     5,     7,    28,     8,    18,    23,
  275.     30,    35,    32,    19,     9,    29,    25,    36,    33,     0,
  276.      0,     0,    16,    27,     0,    26,    22,    39,    20,    24,
  277.     40,    11,     0,    10,     0,    39,    21,    13,    12,     0,
  278.      0
  279. };
  280.  
  281. static const short yydefgoto[] = {     1,
  282.     11,    12,    13,    14,    15,    16,    17,    18,    44
  283. };
  284.  
  285. static const short yypact[] = {-32768,
  286.      0,-   15,-32768,-32768,-   10,-32768,-32768,    25,    11,-    8,
  287. -32768,-32768,-32768,-32768,-32768,-32768,    13,-32768,-32768,     7,
  288. -32768,-32768,-32768,-32768,-32768,-32768,     4,-32768,-32768,    14,
  289.     15,    19,-32768,-32768,    24,-32768,-32768,    18,    20,-32768,
  290. -32768,-32768,    26,-32768,    27,-    6,-32768,-32768,-32768,    31,
  291. -32768
  292. };
  293.  
  294. static const short yypgoto[] = {-32768,
  295. -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-    5
  296. };
  297.  
  298.  
  299. #define    YYLAST        41
  300.  
  301.  
  302. static const short yytable[] = {    50,
  303.     41,    19,    20,     2,     3,    48,    33,     4,     5,     6,
  304.      7,     8,     9,    10,    24,    34,    36,    25,    26,    27,
  305.     28,    29,    30,    35,    41,    37,    31,    38,    32,    42,
  306.     51,    39,    21,    43,    22,    23,    40,    45,    46,    47,
  307.     49
  308. };
  309.  
  310. static const short yycheck[] = {     0,
  311.      7,    17,    13,     4,     5,    12,    15,     8,     9,    10,
  312.     11,    12,    13,    14,     4,     3,    13,     7,     8,     9,
  313.     10,    11,    12,    17,     7,    12,    16,    13,    18,    12,
  314.      0,    13,     8,    16,    10,    11,    13,    18,    13,    13,
  315.     46
  316. };
  317. /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
  318. #line 3 "bison.simple"
  319.  
  320. /* Skeleton output parser for bison,
  321.    Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman
  322.  
  323.    This program is free software; you can redistribute it and/or modify
  324.    it under the terms of the GNU General Public License as published by
  325.    the Free Software Foundation; either version 1, or (at your option)
  326.    any later version.
  327.  
  328.    This program is distributed in the hope that it will be useful,
  329.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  330.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  331.    GNU General Public License for more details.
  332.  
  333.    You should have received a copy of the GNU General Public License
  334.    along with this program; if not, write to the Free Software
  335.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  336.  
  337.  
  338. #ifndef alloca
  339. #ifdef __GNUC__
  340. #define alloca __builtin_alloca
  341. #else /* Not GNU C.  */
  342. #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__)
  343. #include <alloca.h>
  344. #else /* Not sparc */
  345. #ifdef MSDOS
  346. #include <malloc.h>
  347. #endif /* MSDOS */
  348. #endif /* Not sparc.  */
  349. #endif /* Not GNU C.  */
  350. #endif /* alloca not defined.  */
  351.  
  352. /* This is the parser code that is written into each bison parser
  353.   when the %semantic_parser declaration is not specified in the grammar.
  354.   It was written by Richard Stallman by simplifying the hairy parser
  355.   used when %semantic_parser is specified.  */
  356.  
  357. /* Note: there must be only one dollar sign in this file.
  358.    It is replaced by the list of actions, each action
  359.    as one case of the switch.  */
  360.  
  361. #define yyerrok        (yyerrstatus = 0)
  362. #define yyclearin    (yychar = YYEMPTY)
  363. #define YYEMPTY        -2
  364. #define YYEOF        0
  365. #define YYACCEPT    return(0)
  366. #define YYABORT     return(1)
  367. #define YYERROR        goto yyerrlab1
  368. /* Like YYERROR except do call yyerror.
  369.    This remains here temporarily to ease the
  370.    transition to the new meaning of YYERROR, for GCC.
  371.    Once GCC version 2 has supplanted version 1, this can go.  */
  372. #define YYFAIL        goto yyerrlab
  373. #define YYRECOVERING()  (!!yyerrstatus)
  374. #define YYBACKUP(token, value) \
  375. do                                \
  376.   if (yychar == YYEMPTY && yylen == 1)                \
  377.     { yychar = (token), yylval = (value);            \
  378.       yychar1 = YYTRANSLATE (yychar);                \
  379.       YYPOPSTACK;                        \
  380.       goto yybackup;                        \
  381.     }                                \
  382.   else                                \
  383.     { yyerror ("syntax error: cannot back up"); YYERROR; }    \
  384. while (0)
  385.  
  386. #define YYTERROR    1
  387. #define YYERRCODE    256
  388.  
  389. #ifndef YYPURE
  390. #define YYLEX        yylex()
  391. #endif
  392.  
  393. #ifdef YYPURE
  394. #ifdef YYLSP_NEEDED
  395. #define YYLEX        yylex(&yylval, &yylloc)
  396. #else
  397. #define YYLEX        yylex(&yylval)
  398. #endif
  399. #endif
  400.  
  401. /* If nonreentrant, generate the variables here */
  402.  
  403. #ifndef YYPURE
  404.  
  405. int    yychar;            /*  the lookahead symbol        */
  406. YYSTYPE    yylval;            /*  the semantic value of the        */
  407.                 /*  lookahead symbol            */
  408.  
  409. #ifdef YYLSP_NEEDED
  410. YYLTYPE yylloc;            /*  location data for the lookahead    */
  411.                 /*  symbol                */
  412. #endif
  413.  
  414. int yynerrs;            /*  number of parse errors so far       */
  415. #endif  /* not YYPURE */
  416.  
  417. #if YYDEBUG != 0
  418. int yydebug;            /*  nonzero means print parse trace    */
  419. /* Since this is uninitialized, it does not stop multiple parsers
  420.    from coexisting.  */
  421. #endif
  422.  
  423. /*  YYINITDEPTH indicates the initial size of the parser's stacks    */
  424.  
  425. #ifndef    YYINITDEPTH
  426. #define YYINITDEPTH 200
  427. #endif
  428.  
  429. /*  YYMAXDEPTH is the maximum size the stacks can grow to
  430.     (effective only if the built-in stack extension method is used).  */
  431.  
  432. #if YYMAXDEPTH == 0
  433. #undef YYMAXDEPTH
  434. #endif
  435.  
  436. #ifndef YYMAXDEPTH
  437. #define YYMAXDEPTH 10000
  438. #endif
  439.  
  440. #ifndef __cplusplus
  441.  
  442. /* This is the most reliable way to avoid incompatibilities
  443.    in available built-in functions on various systems.  */
  444. static void
  445. __yy_bcopy (from, to, count)
  446.      char *from;
  447.      char *to;
  448.      int count;
  449. {
  450.   register char *f = from;
  451.   register char *t = to;
  452.   register int i = count;
  453.  
  454.   while (i-- > 0)
  455.     *t++ = *f++;
  456. }
  457.  
  458. #else /* __cplusplus */
  459.  
  460. /* This is the most reliable way to avoid incompatibilities
  461.    in available built-in functions on various systems.  */
  462. static void
  463. __yy_bcopy (char *from, char *to, int count)
  464. {
  465.   register char *f = from;
  466.   register char *t = to;
  467.   register int i = count;
  468.  
  469.   while (i-- > 0)
  470.     *t++ = *f++;
  471. }
  472.  
  473. #endif
  474.  
  475. #line 160 "bison.simple"
  476. int
  477. yyparse()
  478. {
  479.   register int yystate;
  480.   register int yyn;
  481.   register short *yyssp;
  482.   register YYSTYPE *yyvsp;
  483.   int yyerrstatus;    /*  number of tokens to shift before error messages enabled */
  484.   int yychar1;        /*  lookahead token as an internal (translated) token number */
  485.  
  486.   short    yyssa[YYINITDEPTH];    /*  the state stack            */
  487.   YYSTYPE yyvsa[YYINITDEPTH];    /*  the semantic value stack        */
  488.  
  489.   short *yyss = yyssa;        /*  refer to the stacks thru separate pointers */
  490.   YYSTYPE *yyvs = yyvsa;    /*  to allow yyoverflow to reallocate them elsewhere */
  491.  
  492. #ifdef YYLSP_NEEDED
  493.   YYLTYPE *yyls = yylsa;
  494.   YYLTYPE *yylsp;
  495.   YYLTYPE yylsa[YYINITDEPTH];    /*  the location stack            */
  496.  
  497. #define YYPOPSTACK   (yyvsp--, yysp--, yylsp--)
  498. #else
  499. #define YYPOPSTACK   (yyvsp--, yysp--)
  500. #endif
  501.  
  502.   int yystacksize = YYINITDEPTH;
  503.  
  504. #ifdef YYPURE
  505.   int yychar;
  506.   YYSTYPE yylval;
  507.   int yynerrs;
  508. #ifdef YYLSP_NEEDED
  509.   YYLTYPE yylloc;
  510. #endif
  511. #endif
  512.  
  513.   YYSTYPE yyval;        /*  the variable used to return        */
  514.                 /*  semantic values from the action    */
  515.                 /*  routines                */
  516.  
  517.   int yylen;
  518.  
  519. #if YYDEBUG != 0
  520.   if (yydebug)
  521.     fprintf(stderr, "Starting parse\n");
  522. #endif
  523.  
  524.   yystate = 0;
  525.   yyerrstatus = 0;
  526.   yynerrs = 0;
  527.   yychar = YYEMPTY;        /* Cause a token to be read.  */
  528.  
  529.   /* Initialize stack pointers.
  530.      Waste one element of value and location stack
  531.      so that they stay on the same level as the state stack.  */
  532.  
  533.   yyssp = yyss - 1;
  534.   yyvsp = yyvs;
  535. #ifdef YYLSP_NEEDED
  536.   yylsp = yyls;
  537. #endif
  538.  
  539. /* Push a new state, which is found in  yystate  .  */
  540. /* In all cases, when you get here, the value and location stacks
  541.    have just been pushed. so pushing a state here evens the stacks.  */
  542. yynewstate:
  543.  
  544.   *++yyssp = yystate;
  545.  
  546.   if (yyssp >= yyss + yystacksize - 1)
  547.     {
  548.       /* Give user a chance to reallocate the stack */
  549.       /* Use copies of these so that the &'s don't force the real ones into memory. */
  550.       YYSTYPE *yyvs1 = yyvs;
  551.       short *yyss1 = yyss;
  552. #ifdef YYLSP_NEEDED
  553.       YYLTYPE *yyls1 = yyls;
  554. #endif
  555.  
  556.       /* Get the current used size of the three stacks, in elements.  */
  557.       int size = yyssp - yyss + 1;
  558.  
  559. #ifdef yyoverflow
  560.       /* Each stack pointer address is followed by the size of
  561.      the data in use in that stack, in bytes.  */
  562.       yyoverflow("parser stack overflow",
  563.          &yyss1, size * sizeof (*yyssp),
  564.          &yyvs1, size * sizeof (*yyvsp),
  565. #ifdef YYLSP_NEEDED
  566.          &yyls1, size * sizeof (*yylsp),
  567. #endif
  568.          &yystacksize);
  569.  
  570.       yyss = yyss1; yyvs = yyvs1;
  571. #ifdef YYLSP_NEEDED
  572.       yyls = yyls1;
  573. #endif
  574. #else /* no yyoverflow */
  575.       /* Extend the stack our own way.  */
  576.       if (yystacksize >= YYMAXDEPTH)
  577.     {
  578.       yyerror("parser stack overflow");
  579.       return 2;
  580.     }
  581.       yystacksize *= 2;
  582.       if (yystacksize > YYMAXDEPTH)
  583.     yystacksize = YYMAXDEPTH;
  584.       yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
  585.       __yy_bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
  586.       yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
  587.       __yy_bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
  588. #ifdef YYLSP_NEEDED
  589.       yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
  590.       __yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
  591. #endif
  592. #endif /* no yyoverflow */
  593.  
  594.       yyssp = yyss + size - 1;
  595.       yyvsp = yyvs + size - 1;
  596. #ifdef YYLSP_NEEDED
  597.       yylsp = yyls + size - 1;
  598. #endif
  599.  
  600. #if YYDEBUG != 0
  601.       if (yydebug)
  602.     fprintf(stderr, "Stack size increased to %d\n", yystacksize);
  603. #endif
  604.  
  605.       if (yyssp >= yyss + yystacksize - 1)
  606.     YYABORT;
  607.     }
  608.  
  609. #if YYDEBUG != 0
  610.   if (yydebug)
  611.     fprintf(stderr, "Entering state %d\n", yystate);
  612. #endif
  613.  
  614.  yybackup:
  615.  
  616. /* Do appropriate processing given the current state.  */
  617. /* Read a lookahead token if we need one and don't already have one.  */
  618. /* yyresume: */
  619.  
  620.   /* First try to decide what to do without reference to lookahead token.  */
  621.  
  622.   yyn = yypact[yystate];
  623.   if (yyn == YYFLAG)
  624.     goto yydefault;
  625.  
  626.   /* Not known => get a lookahead token if don't already have one.  */
  627.  
  628.   /* yychar is either YYEMPTY or YYEOF
  629.      or a valid token in external form.  */
  630.  
  631.   if (yychar == YYEMPTY)
  632.     {
  633. #if YYDEBUG != 0
  634.       if (yydebug)
  635.     fprintf(stderr, "Reading a token: ");
  636. #endif
  637.       yychar = YYLEX;
  638.     }
  639.  
  640.   /* Convert token to internal form (in yychar1) for indexing tables with */
  641.  
  642.   if (yychar <= 0)        /* This means end of input. */
  643.     {
  644.       yychar1 = 0;
  645.       yychar = YYEOF;        /* Don't call YYLEX any more */
  646.  
  647. #if YYDEBUG != 0
  648.       if (yydebug)
  649.     fprintf(stderr, "Now at end of input.\n");
  650. #endif
  651.     }
  652.   else
  653.     {
  654.       yychar1 = YYTRANSLATE(yychar);
  655.  
  656. #if YYDEBUG != 0
  657.       if (yydebug)
  658.     fprintf(stderr, "Next token is %d (%s)\n", yychar, yytname[yychar1]);
  659. #endif
  660.     }
  661.  
  662.   yyn += yychar1;
  663.   if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
  664.     goto yydefault;
  665.  
  666.   yyn = yytable[yyn];
  667.  
  668.   /* yyn is what to do for this token type in this state.
  669.      Negative => reduce, -yyn is rule number.
  670.      Positive => shift, yyn is new state.
  671.        New state is final state => don't bother to shift,
  672.        just return success.
  673.      0, or most negative number => error.  */
  674.  
  675.   if (yyn < 0)
  676.     {
  677.       if (yyn == YYFLAG)
  678.     goto yyerrlab;
  679.       yyn = -yyn;
  680.       goto yyreduce;
  681.     }
  682.   else if (yyn == 0)
  683.     goto yyerrlab;
  684.  
  685.   if (yyn == YYFINAL)
  686.     YYACCEPT;
  687.  
  688.   /* Shift the lookahead token.  */
  689.  
  690. #if YYDEBUG != 0
  691.   if (yydebug)
  692.     fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
  693. #endif
  694.  
  695.   /* Discard the token being shifted unless it is eof.  */
  696.   if (yychar != YYEOF)
  697.     yychar = YYEMPTY;
  698.  
  699.   *++yyvsp = yylval;
  700. #ifdef YYLSP_NEEDED
  701.   *++yylsp = yylloc;
  702. #endif
  703.  
  704.   /* count tokens shifted since error; after three, turn off error status.  */
  705.   if (yyerrstatus) yyerrstatus--;
  706.  
  707.   yystate = yyn;
  708.   goto yynewstate;
  709.  
  710. /* Do the default action for the current state.  */
  711. yydefault:
  712.  
  713.   yyn = yydefact[yystate];
  714.   if (yyn == 0)
  715.     goto yyerrlab;
  716.  
  717. /* Do a reduction.  yyn is the number of a rule to reduce with.  */
  718. yyreduce:
  719.   yylen = yyr2[yyn];
  720.   yyval = yyvsp[1-yylen]; /* implement default value of the action */
  721.  
  722. #if YYDEBUG != 0
  723.   if (yydebug)
  724.     {
  725.       int i;
  726.  
  727.       fprintf (stderr, "Reducing via rule %d (line %d), ",
  728.            yyn, yyrline[yyn]);
  729.  
  730.       /* Print the symboles being reduced, and their result.  */
  731.       for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
  732.     fprintf (stderr, "%s ", yytname[yyrhs[i]]);
  733.       fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
  734.     }
  735. #endif
  736.  
  737.  
  738.   switch (yyn) {
  739.  
  740. case 3:
  741. #line 156 "getdate.y"
  742. {
  743.         yyHaveTime++;
  744.     ;
  745.     break;}
  746. case 4:
  747. #line 159 "getdate.y"
  748. {
  749.         yyHaveZone++;
  750.     ;
  751.     break;}
  752. case 5:
  753. #line 162 "getdate.y"
  754. {
  755.         yyHaveDate++;
  756.     ;
  757.     break;}
  758. case 6:
  759. #line 165 "getdate.y"
  760. {
  761.         yyHaveDay++;
  762.     ;
  763.     break;}
  764. case 7:
  765. #line 168 "getdate.y"
  766. {
  767.         yyHaveRel++;
  768.     ;
  769.     break;}
  770. case 9:
  771. #line 174 "getdate.y"
  772. {
  773.         yyHour = yyvsp[-1].Number;
  774.         yyMinutes = 0;
  775.         yySeconds = 0;
  776.         yyMeridian = yyvsp[0].Meridian;
  777.     ;
  778.     break;}
  779. case 10:
  780. #line 180 "getdate.y"
  781. {
  782.         yyHour = yyvsp[-3].Number;
  783.         yyMinutes = yyvsp[-1].Number;
  784.         yySeconds = 0;
  785.         yyMeridian = yyvsp[0].Meridian;
  786.     ;
  787.     break;}
  788. case 11:
  789. #line 186 "getdate.y"
  790. {
  791.         yyHour = yyvsp[-3].Number;
  792.         yyMinutes = yyvsp[-1].Number;
  793.         yyMeridian = MER24;
  794.         yyDSTmode = DSToff;
  795.         yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
  796.     ;
  797.     break;}
  798. case 12:
  799. #line 193 "getdate.y"
  800. {
  801.         yyHour = yyvsp[-5].Number;
  802.         yyMinutes = yyvsp[-3].Number;
  803.         yySeconds = yyvsp[-1].Number;
  804.         yyMeridian = yyvsp[0].Meridian;
  805.     ;
  806.     break;}
  807. case 13:
  808. #line 199 "getdate.y"
  809. {
  810.         yyHour = yyvsp[-5].Number;
  811.         yyMinutes = yyvsp[-3].Number;
  812.         yySeconds = yyvsp[-1].Number;
  813.         yyMeridian = MER24;
  814.         yyDSTmode = DSToff;
  815.         yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
  816.     ;
  817.     break;}
  818. case 14:
  819. #line 209 "getdate.y"
  820. {
  821.         yyTimezone = yyvsp[0].Number;
  822.         yyDSTmode = DSToff;
  823.     ;
  824.     break;}
  825. case 15:
  826. #line 213 "getdate.y"
  827. {
  828.         yyTimezone = yyvsp[0].Number;
  829.         yyDSTmode = DSTon;
  830.     ;
  831.     break;}
  832. case 16:
  833. #line 218 "getdate.y"
  834. {
  835.         yyTimezone = yyvsp[-1].Number;
  836.         yyDSTmode = DSTon;
  837.     ;
  838.     break;}
  839. case 17:
  840. #line 224 "getdate.y"
  841. {
  842.         yyDayOrdinal = 1;
  843.         yyDayNumber = yyvsp[0].Number;
  844.     ;
  845.     break;}
  846. case 18:
  847. #line 228 "getdate.y"
  848. {
  849.         yyDayOrdinal = 1;
  850.         yyDayNumber = yyvsp[-1].Number;
  851.     ;
  852.     break;}
  853. case 19:
  854. #line 232 "getdate.y"
  855. {
  856.         yyDayOrdinal = yyvsp[-1].Number;
  857.         yyDayNumber = yyvsp[0].Number;
  858.     ;
  859.     break;}
  860. case 20:
  861. #line 238 "getdate.y"
  862. {
  863.         yyMonth = yyvsp[-2].Number;
  864.         yyDay = yyvsp[0].Number;
  865.     ;
  866.     break;}
  867. case 21:
  868. #line 242 "getdate.y"
  869. {
  870.         yyMonth = yyvsp[-4].Number;
  871.         yyDay = yyvsp[-2].Number;
  872.         yyYear = yyvsp[0].Number;
  873.     ;
  874.     break;}
  875. case 22:
  876. #line 247 "getdate.y"
  877. {
  878.         /* ISO 8601 format.  yyyy-mm-dd.  */
  879.         yyYear = yyvsp[-2].Number;
  880.         yyMonth = -yyvsp[-1].Number;
  881.         yyDay = -yyvsp[0].Number;
  882.     ;
  883.     break;}
  884. case 23:
  885. #line 253 "getdate.y"
  886. {
  887.         yyMonth = yyvsp[-1].Number;
  888.         yyDay = yyvsp[0].Number;
  889.     ;
  890.     break;}
  891. case 24:
  892. #line 257 "getdate.y"
  893. {
  894.         yyMonth = yyvsp[-3].Number;
  895.         yyDay = yyvsp[-2].Number;
  896.         yyYear = yyvsp[0].Number;
  897.     ;
  898.     break;}
  899. case 25:
  900. #line 262 "getdate.y"
  901. {
  902.         yyMonth = yyvsp[0].Number;
  903.         yyDay = yyvsp[-1].Number;
  904.     ;
  905.     break;}
  906. case 26:
  907. #line 266 "getdate.y"
  908. {
  909.         yyMonth = yyvsp[-1].Number;
  910.         yyDay = yyvsp[-2].Number;
  911.         yyYear = yyvsp[0].Number;
  912.     ;
  913.     break;}
  914. case 27:
  915. #line 273 "getdate.y"
  916. {
  917.         yyRelSeconds = -yyRelSeconds;
  918.         yyRelMonth = -yyRelMonth;
  919.     ;
  920.     break;}
  921. case 29:
  922. #line 280 "getdate.y"
  923. {
  924.         yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number * 60L;
  925.     ;
  926.     break;}
  927. case 30:
  928. #line 283 "getdate.y"
  929. {
  930.         yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number * 60L;
  931.     ;
  932.     break;}
  933. case 31:
  934. #line 286 "getdate.y"
  935. {
  936.         yyRelSeconds += yyvsp[0].Number * 60L;
  937.     ;
  938.     break;}
  939. case 32:
  940. #line 289 "getdate.y"
  941. {
  942.         yyRelSeconds += yyvsp[-1].Number;
  943.     ;
  944.     break;}
  945. case 33:
  946. #line 292 "getdate.y"
  947. {
  948.         yyRelSeconds += yyvsp[-1].Number;
  949.     ;
  950.     break;}
  951. case 34:
  952. #line 295 "getdate.y"
  953. {
  954.         yyRelSeconds++;
  955.     ;
  956.     break;}
  957. case 35:
  958. #line 298 "getdate.y"
  959. {
  960.         yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
  961.     ;
  962.     break;}
  963. case 36:
  964. #line 301 "getdate.y"
  965. {
  966.         yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
  967.     ;
  968.     break;}
  969. case 37:
  970. #line 304 "getdate.y"
  971. {
  972.         yyRelMonth += yyvsp[0].Number;
  973.     ;
  974.     break;}
  975. case 38:
  976. #line 309 "getdate.y"
  977. {
  978.         if (yyHaveTime && yyHaveDate && !yyHaveRel)
  979.         yyYear = yyvsp[0].Number;
  980.         else {
  981.         if(yyvsp[0].Number>10000) {
  982.             time_t date_part;
  983.  
  984.             date_part= yyvsp[0].Number/10000;
  985.             yyHaveDate++;
  986.             yyDay= (date_part)%100;
  987.             yyMonth= (date_part/100)%100;
  988.             yyYear = date_part/10000;
  989.         } 
  990.             yyHaveTime++;
  991.         if (yyvsp[0].Number < 100) {
  992.             yyHour = yyvsp[0].Number;
  993.             yyMinutes = 0;
  994.         }
  995.         else {
  996.             yyHour = yyvsp[0].Number / 100;
  997.             yyMinutes = yyvsp[0].Number % 100;
  998.         }
  999.         yySeconds = 0;
  1000.         yyMeridian = MER24;
  1001.         }
  1002.     ;
  1003.     break;}
  1004. case 39:
  1005. #line 337 "getdate.y"
  1006. {
  1007.         yyval.Meridian = MER24;
  1008.     ;
  1009.     break;}
  1010. case 40:
  1011. #line 340 "getdate.y"
  1012. {
  1013.         yyval.Meridian = yyvsp[0].Meridian;
  1014.     ;
  1015.     break;}
  1016. }
  1017.    /* the action file gets copied in in place of this dollarsign */
  1018. #line 423 "bison.simple"
  1019.  
  1020.   yyvsp -= yylen;
  1021.   yyssp -= yylen;
  1022. #ifdef YYLSP_NEEDED
  1023.   yylsp -= yylen;
  1024. #endif
  1025.  
  1026. #if YYDEBUG != 0
  1027.   if (yydebug)
  1028.     {
  1029.       short *ssp1 = yyss - 1;
  1030.       fprintf (stderr, "state stack now");
  1031.       while (ssp1 != yyssp)
  1032.     fprintf (stderr, " %d", *++ssp1);
  1033.       fprintf (stderr, "\n");
  1034.     }
  1035. #endif
  1036.  
  1037.   *++yyvsp = yyval;
  1038.  
  1039. #ifdef YYLSP_NEEDED
  1040.   yylsp++;
  1041.   if (yylen == 0)
  1042.     {
  1043.       yylsp->first_line = yylloc.first_line;
  1044.       yylsp->first_column = yylloc.first_column;
  1045.       yylsp->last_line = (yylsp-1)->last_line;
  1046.       yylsp->last_column = (yylsp-1)->last_column;
  1047.       yylsp->text = 0;
  1048.     }
  1049.   else
  1050.     {
  1051.       yylsp->last_line = (yylsp+yylen-1)->last_line;
  1052.       yylsp->last_column = (yylsp+yylen-1)->last_column;
  1053.     }
  1054. #endif
  1055.  
  1056.   /* Now "shift" the result of the reduction.
  1057.      Determine what state that goes to,
  1058.      based on the state we popped back to
  1059.      and the rule number reduced by.  */
  1060.  
  1061.   yyn = yyr1[yyn];
  1062.  
  1063.   yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
  1064.   if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
  1065.     yystate = yytable[yystate];
  1066.   else
  1067.     yystate = yydefgoto[yyn - YYNTBASE];
  1068.  
  1069.   goto yynewstate;
  1070.  
  1071. yyerrlab:   /* here on detecting error */
  1072.  
  1073.   if (! yyerrstatus)
  1074.     /* If not already recovering from an error, report this error.  */
  1075.     {
  1076.       ++yynerrs;
  1077.  
  1078. #ifdef YYERROR_VERBOSE
  1079.       yyn = yypact[yystate];
  1080.  
  1081.       if (yyn > YYFLAG && yyn < YYLAST)
  1082.     {
  1083.       int size = 0;
  1084.       char *msg;
  1085.       int x, count;
  1086.  
  1087.       count = 0;
  1088.       for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++)
  1089.         if (yycheck[x + yyn] == x)
  1090.           size += strlen(yytname[x]) + 15, count++;
  1091.       msg = (char *) xmalloc(size + 15);
  1092.       strcpy(msg, "parse error");
  1093.  
  1094.       if (count < 5)
  1095.         {
  1096.           count = 0;
  1097.           for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++)
  1098.         if (yycheck[x + yyn] == x)
  1099.           {
  1100.             strcat(msg, count == 0 ? ", expecting `" : " or `");
  1101.             strcat(msg, yytname[x]);
  1102.             strcat(msg, "'");
  1103.             count++;
  1104.           }
  1105.         }
  1106.       yyerror(msg);
  1107.       free(msg);
  1108.     }
  1109.       else
  1110. #endif /* YYERROR_VERBOSE */
  1111.     yyerror("parse error");
  1112.     }
  1113.  
  1114. yyerrlab1:   /* here on error raised explicitly by an action */
  1115.  
  1116.   if (yyerrstatus == 3)
  1117.     {
  1118.       /* if just tried and failed to reuse lookahead token after an error, discard it.  */
  1119.  
  1120.       /* return failure if at end of input */
  1121.       if (yychar == YYEOF)
  1122.     YYABORT;
  1123.  
  1124. #if YYDEBUG != 0
  1125.       if (yydebug)
  1126.     fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
  1127. #endif
  1128.  
  1129.       yychar = YYEMPTY;
  1130.     }
  1131.  
  1132.   /* Else will try to reuse lookahead token
  1133.      after shifting the error token.  */
  1134.  
  1135.   yyerrstatus = 3;        /* Each real token shifted decrements this */
  1136.  
  1137.   goto yyerrhandle;
  1138.  
  1139. yyerrdefault:  /* current state does not do anything special for the error token. */
  1140.  
  1141. #if 0
  1142.   /* This is wrong; only states that explicitly want error tokens
  1143.      should shift them.  */
  1144.   yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
  1145.   if (yyn) goto yydefault;
  1146. #endif
  1147.  
  1148. yyerrpop:   /* pop the current state because it cannot handle the error token */
  1149.  
  1150.   if (yyssp == yyss) YYABORT;
  1151.   yyvsp--;
  1152.   yystate = *--yyssp;
  1153. #ifdef YYLSP_NEEDED
  1154.   yylsp--;
  1155. #endif
  1156.  
  1157. #if YYDEBUG != 0
  1158.   if (yydebug)
  1159.     {
  1160.       short *ssp1 = yyss - 1;
  1161.       fprintf (stderr, "Error: state stack now");
  1162.       while (ssp1 != yyssp)
  1163.     fprintf (stderr, " %d", *++ssp1);
  1164.       fprintf (stderr, "\n");
  1165.     }
  1166. #endif
  1167.  
  1168. yyerrhandle:
  1169.  
  1170.   yyn = yypact[yystate];
  1171.   if (yyn == YYFLAG)
  1172.     goto yyerrdefault;
  1173.  
  1174.   yyn += YYTERROR;
  1175.   if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
  1176.     goto yyerrdefault;
  1177.  
  1178.   yyn = yytable[yyn];
  1179.   if (yyn < 0)
  1180.     {
  1181.       if (yyn == YYFLAG)
  1182.     goto yyerrpop;
  1183.       yyn = -yyn;
  1184.       goto yyreduce;
  1185.     }
  1186.   else if (yyn == 0)
  1187.     goto yyerrpop;
  1188.  
  1189.   if (yyn == YYFINAL)
  1190.     YYACCEPT;
  1191.  
  1192. #if YYDEBUG != 0
  1193.   if (yydebug)
  1194.     fprintf(stderr, "Shifting error token, ");
  1195. #endif
  1196.  
  1197.   *++yyvsp = yylval;
  1198. #ifdef YYLSP_NEEDED
  1199.   *++yylsp = yylloc;
  1200. #endif
  1201.  
  1202.   yystate = yyn;
  1203.   goto yynewstate;
  1204. }
  1205. #line 345 "getdate.y"
  1206.  
  1207.  
  1208. /* Month and day table. */
  1209. static TABLE    MonthDayTable[] = {
  1210.     { "january",    tMONTH,  1 },
  1211.     { "february",    tMONTH,  2 },
  1212.     { "march",        tMONTH,  3 },
  1213.     { "april",        tMONTH,  4 },
  1214.     { "may",        tMONTH,  5 },
  1215.     { "june",        tMONTH,  6 },
  1216.     { "july",        tMONTH,  7 },
  1217.     { "august",        tMONTH,  8 },
  1218.     { "september",    tMONTH,  9 },
  1219.     { "sept",        tMONTH,  9 },
  1220.     { "october",    tMONTH, 10 },
  1221.     { "november",    tMONTH, 11 },
  1222.     { "december",    tMONTH, 12 },
  1223.     { "sunday",        tDAY, 0 },
  1224.     { "monday",        tDAY, 1 },
  1225.     { "tuesday",    tDAY, 2 },
  1226.     { "tues",        tDAY, 2 },
  1227.     { "wednesday",    tDAY, 3 },
  1228.     { "wednes",        tDAY, 3 },
  1229.     { "thursday",    tDAY, 4 },
  1230.     { "thur",        tDAY, 4 },
  1231.     { "thurs",        tDAY, 4 },
  1232.     { "friday",        tDAY, 5 },
  1233.     { "saturday",    tDAY, 6 },
  1234.     { NULL }
  1235. };
  1236.  
  1237. /* Time units table. */
  1238. static TABLE    UnitsTable[] = {
  1239.     { "year",        tMONTH_UNIT,    12 },
  1240.     { "month",        tMONTH_UNIT,    1 },
  1241.     { "fortnight",    tMINUTE_UNIT,    14 * 24 * 60 },
  1242.     { "week",        tMINUTE_UNIT,    7 * 24 * 60 },
  1243.     { "day",        tMINUTE_UNIT,    1 * 24 * 60 },
  1244.     { "hour",        tMINUTE_UNIT,    60 },
  1245.     { "minute",        tMINUTE_UNIT,    1 },
  1246.     { "min",        tMINUTE_UNIT,    1 },
  1247.     { "second",        tSEC_UNIT,    1 },
  1248.     { "sec",        tSEC_UNIT,    1 },
  1249.     { NULL }
  1250. };
  1251.  
  1252. /* Assorted relative-time words. */
  1253. static TABLE    OtherTable[] = {
  1254.     { "tomorrow",    tMINUTE_UNIT,    1 * 24 * 60 },
  1255.     { "yesterday",    tMINUTE_UNIT,    -1 * 24 * 60 },
  1256.     { "today",        tMINUTE_UNIT,    0 },
  1257.     { "now",        tMINUTE_UNIT,    0 },
  1258.     { "last",        tUNUMBER,    -1 },
  1259.     { "this",        tMINUTE_UNIT,    0 },
  1260.     { "next",        tUNUMBER,    2 },
  1261.     { "first",        tUNUMBER,    1 },
  1262. /*  { "second",        tUNUMBER,    2 }, */
  1263.     { "third",        tUNUMBER,    3 },
  1264.     { "fourth",        tUNUMBER,    4 },
  1265.     { "fifth",        tUNUMBER,    5 },
  1266.     { "sixth",        tUNUMBER,    6 },
  1267.     { "seventh",    tUNUMBER,    7 },
  1268.     { "eighth",        tUNUMBER,    8 },
  1269.     { "ninth",        tUNUMBER,    9 },
  1270.     { "tenth",        tUNUMBER,    10 },
  1271.     { "eleventh",    tUNUMBER,    11 },
  1272.     { "twelfth",    tUNUMBER,    12 },
  1273.     { "ago",        tAGO,    1 },
  1274.     { NULL }
  1275. };
  1276.  
  1277. /* The timezone table. */
  1278. /* Some of these are commented out because a time_t can't store a float. */
  1279. static TABLE    TimezoneTable[] = {
  1280.     { "gmt",    tZONE,     HOUR( 0) },    /* Greenwich Mean */
  1281.     { "ut",    tZONE,     HOUR( 0) },    /* Universal (Coordinated) */
  1282.     { "utc",    tZONE,     HOUR( 0) },
  1283.     { "wet",    tZONE,     HOUR( 0) },    /* Western European */
  1284.     { "bst",    tDAYZONE,  HOUR( 0) },    /* British Summer */
  1285.     { "wat",    tZONE,     HOUR( 1) },    /* West Africa */
  1286.     { "at",    tZONE,     HOUR( 2) },    /* Azores */
  1287. #if    0
  1288.     /* For completeness.  BST is also British Summer, and GST is
  1289.      * also Guam Standard. */
  1290.     { "bst",    tZONE,     HOUR( 3) },    /* Brazil Standard */
  1291.     { "gst",    tZONE,     HOUR( 3) },    /* Greenland Standard */
  1292. #endif
  1293. #if 0
  1294.     { "nft",    tZONE,     HOUR(3.5) },    /* Newfoundland */
  1295.     { "nst",    tZONE,     HOUR(3.5) },    /* Newfoundland Standard */
  1296.     { "ndt",    tDAYZONE,  HOUR(3.5) },    /* Newfoundland Daylight */
  1297. #endif
  1298.     { "ast",    tZONE,     HOUR( 4) },    /* Atlantic Standard */
  1299.     { "adt",    tDAYZONE,  HOUR( 4) },    /* Atlantic Daylight */
  1300.     { "est",    tZONE,     HOUR( 5) },    /* Eastern Standard */
  1301.     { "edt",    tDAYZONE,  HOUR( 5) },    /* Eastern Daylight */
  1302.     { "cst",    tZONE,     HOUR( 6) },    /* Central Standard */
  1303.     { "cdt",    tDAYZONE,  HOUR( 6) },    /* Central Daylight */
  1304.     { "mst",    tZONE,     HOUR( 7) },    /* Mountain Standard */
  1305.     { "mdt",    tDAYZONE,  HOUR( 7) },    /* Mountain Daylight */
  1306.     { "pst",    tZONE,     HOUR( 8) },    /* Pacific Standard */
  1307.     { "pdt",    tDAYZONE,  HOUR( 8) },    /* Pacific Daylight */
  1308.     { "yst",    tZONE,     HOUR( 9) },    /* Yukon Standard */
  1309.     { "ydt",    tDAYZONE,  HOUR( 9) },    /* Yukon Daylight */
  1310.     { "hst",    tZONE,     HOUR(10) },    /* Hawaii Standard */
  1311.     { "hdt",    tDAYZONE,  HOUR(10) },    /* Hawaii Daylight */
  1312.     { "cat",    tZONE,     HOUR(10) },    /* Central Alaska */
  1313.     { "ahst",    tZONE,     HOUR(10) },    /* Alaska-Hawaii Standard */
  1314.     { "nt",    tZONE,     HOUR(11) },    /* Nome */
  1315.     { "idlw",    tZONE,     HOUR(12) },    /* International Date Line West */
  1316.     { "cet",    tZONE,     -HOUR(1) },    /* Central European */
  1317.     { "met",    tZONE,     -HOUR(1) },    /* Middle European */
  1318.     { "mewt",    tZONE,     -HOUR(1) },    /* Middle European Winter */
  1319.     { "mest",    tDAYZONE,  -HOUR(1) },    /* Middle European Summer */
  1320.     { "swt",    tZONE,     -HOUR(1) },    /* Swedish Winter */
  1321.     { "sst",    tDAYZONE,  -HOUR(1) },    /* Swedish Summer */
  1322.     { "fwt",    tZONE,     -HOUR(1) },    /* French Winter */
  1323.     { "fst",    tDAYZONE,  -HOUR(1) },    /* French Summer */
  1324.     { "eet",    tZONE,     -HOUR(2) },    /* Eastern Europe, USSR Zone 1 */
  1325.     { "bt",    tZONE,     -HOUR(3) },    /* Baghdad, USSR Zone 2 */
  1326. #if 0
  1327.     { "it",    tZONE,     -HOUR(3.5) },/* Iran */
  1328. #endif
  1329.     { "zp4",    tZONE,     -HOUR(4) },    /* USSR Zone 3 */
  1330.     { "zp5",    tZONE,     -HOUR(5) },    /* USSR Zone 4 */
  1331. #if 0
  1332.     { "ist",    tZONE,     -HOUR(5.5) },/* Indian Standard */
  1333. #endif
  1334.     { "zp6",    tZONE,     -HOUR(6) },    /* USSR Zone 5 */
  1335. #if    0
  1336.     /* For completeness.  NST is also Newfoundland Stanard, and SST is
  1337.      * also Swedish Summer. */
  1338.     { "nst",    tZONE,     -HOUR(6.5) },/* North Sumatra */
  1339.     { "sst",    tZONE,     -HOUR(7) },    /* South Sumatra, USSR Zone 6 */
  1340. #endif    /* 0 */
  1341.     { "wast",    tZONE,     -HOUR(7) },    /* West Australian Standard */
  1342.     { "wadt",    tDAYZONE,  -HOUR(7) },    /* West Australian Daylight */
  1343. #if 0
  1344.     { "jt",    tZONE,     -HOUR(7.5) },/* Java (3pm in Cronusland!) */
  1345. #endif
  1346.     { "cct",    tZONE,     -HOUR(8) },    /* China Coast, USSR Zone 7 */
  1347.     { "jst",    tZONE,     -HOUR(9) },    /* Japan Standard, USSR Zone 8 */
  1348. #if 0
  1349.     { "cast",    tZONE,     -HOUR(9.5) },/* Central Australian Standard */
  1350.     { "cadt",    tDAYZONE,  -HOUR(9.5) },/* Central Australian Daylight */
  1351. #endif
  1352.     { "east",    tZONE,     -HOUR(10) },    /* Eastern Australian Standard */
  1353.     { "eadt",    tDAYZONE,  -HOUR(10) },    /* Eastern Australian Daylight */
  1354.     { "gst",    tZONE,     -HOUR(10) },    /* Guam Standard, USSR Zone 9 */
  1355.     { "nzt",    tZONE,     -HOUR(12) },    /* New Zealand */
  1356.     { "nzst",    tZONE,     -HOUR(12) },    /* New Zealand Standard */
  1357.     { "nzdt",    tDAYZONE,  -HOUR(12) },    /* New Zealand Daylight */
  1358.     { "idle",    tZONE,     -HOUR(12) },    /* International Date Line East */
  1359.     {  NULL  }
  1360. };
  1361.  
  1362. /* Military timezone table. */
  1363. static TABLE    MilitaryTable[] = {
  1364.     { "a",    tZONE,    HOUR(  1) },
  1365.     { "b",    tZONE,    HOUR(  2) },
  1366.     { "c",    tZONE,    HOUR(  3) },
  1367.     { "d",    tZONE,    HOUR(  4) },
  1368.     { "e",    tZONE,    HOUR(  5) },
  1369.     { "f",    tZONE,    HOUR(  6) },
  1370.     { "g",    tZONE,    HOUR(  7) },
  1371.     { "h",    tZONE,    HOUR(  8) },
  1372.     { "i",    tZONE,    HOUR(  9) },
  1373.     { "k",    tZONE,    HOUR( 10) },
  1374.     { "l",    tZONE,    HOUR( 11) },
  1375.     { "m",    tZONE,    HOUR( 12) },
  1376.     { "n",    tZONE,    HOUR(- 1) },
  1377.     { "o",    tZONE,    HOUR(- 2) },
  1378.     { "p",    tZONE,    HOUR(- 3) },
  1379.     { "q",    tZONE,    HOUR(- 4) },
  1380.     { "r",    tZONE,    HOUR(- 5) },
  1381.     { "s",    tZONE,    HOUR(- 6) },
  1382.     { "t",    tZONE,    HOUR(- 7) },
  1383.     { "u",    tZONE,    HOUR(- 8) },
  1384.     { "v",    tZONE,    HOUR(- 9) },
  1385.     { "w",    tZONE,    HOUR(-10) },
  1386.     { "x",    tZONE,    HOUR(-11) },
  1387.     { "y",    tZONE,    HOUR(-12) },
  1388.     { "z",    tZONE,    HOUR(  0) },
  1389.     { NULL }
  1390. };
  1391.  
  1392.  
  1393.  
  1394.  
  1395. /* ARGSUSED */
  1396. int
  1397. yyerror(s)
  1398.     char    *s;
  1399. {
  1400.   return 0;
  1401. }
  1402.  
  1403.  
  1404. static time_t
  1405. ToSeconds(Hours, Minutes, Seconds, Meridian)
  1406.     time_t    Hours;
  1407.     time_t    Minutes;
  1408.     time_t    Seconds;
  1409.     MERIDIAN    Meridian;
  1410. {
  1411.     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
  1412.     return -1;
  1413.     switch (Meridian) {
  1414.     case MER24:
  1415.     if (Hours < 0 || Hours > 23)
  1416.         return -1;
  1417.     return (Hours * 60L + Minutes) * 60L + Seconds;
  1418.     case MERam:
  1419.     if (Hours < 1 || Hours > 12)
  1420.         return -1;
  1421.     return (Hours * 60L + Minutes) * 60L + Seconds;
  1422.     case MERpm:
  1423.     if (Hours < 1 || Hours > 12)
  1424.         return -1;
  1425.     return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
  1426.     }
  1427.     /* NOTREACHED */
  1428. }
  1429.  
  1430.  
  1431. static time_t
  1432. Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
  1433.     time_t    Month;
  1434.     time_t    Day;
  1435.     time_t    Year;
  1436.     time_t    Hours;
  1437.     time_t    Minutes;
  1438.     time_t    Seconds;
  1439.     MERIDIAN    Meridian;
  1440.     DSTMODE    DSTmode;
  1441. {
  1442.     static int    DaysInMonth[12] = {
  1443.     31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  1444.     };
  1445.     time_t    tod;
  1446.     time_t    Julian;
  1447.     int        i;
  1448.  
  1449.     if (Year < 0)
  1450.     Year = -Year;
  1451.     if (Year < 100)
  1452.     Year += 1900;
  1453.     DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
  1454.             ? 29 : 28;
  1455.     if (Year < EPOCH || Year > 1999
  1456.      || Month < 1 || Month > 12
  1457.      /* Lint fluff:  "conversion from long may lose accuracy" */
  1458.      || Day < 1 || Day > DaysInMonth[(int)--Month])
  1459.     return -1;
  1460.  
  1461.     for (Julian = Day - 1, i = 0; i < Month; i++)
  1462.     Julian += DaysInMonth[i];
  1463.     for (i = EPOCH; i < Year; i++)
  1464.     Julian += 365 + (i % 4 == 0);
  1465.     Julian *= SECSPERDAY;
  1466.     Julian += yyTimezone * 60L;
  1467.     if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
  1468.     return -1;
  1469.     Julian += tod;
  1470.     if (DSTmode == DSTon
  1471.      || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
  1472.     Julian -= 60 * 60;
  1473.     return Julian;
  1474. }
  1475.  
  1476.  
  1477. static time_t
  1478. DSTcorrect(Start, Future)
  1479.     time_t    Start;
  1480.     time_t    Future;
  1481. {
  1482.     time_t    StartDay;
  1483.     time_t    FutureDay;
  1484.  
  1485.     StartDay = (localtime(&Start)->tm_hour + 1) % 24;
  1486.     FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
  1487.     return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
  1488. }
  1489.  
  1490.  
  1491. static time_t
  1492. RelativeDate(Start, DayOrdinal, DayNumber)
  1493.     time_t    Start;
  1494.     time_t    DayOrdinal;
  1495.     time_t    DayNumber;
  1496. {
  1497.     struct tm    *tm;
  1498.     time_t    now;
  1499.  
  1500.     now = Start;
  1501.     tm = localtime(&now);
  1502.     now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
  1503.     now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
  1504.     return DSTcorrect(Start, now);
  1505. }
  1506.  
  1507.  
  1508. static time_t
  1509. RelativeMonth(Start, RelMonth)
  1510.     time_t    Start;
  1511.     time_t    RelMonth;
  1512. {
  1513.     struct tm    *tm;
  1514.     time_t    Month;
  1515.     time_t    Year;
  1516.  
  1517.     if (RelMonth == 0)
  1518.     return 0;
  1519.     tm = localtime(&Start);
  1520.     Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
  1521.     Year = Month / 12;
  1522.     Month = Month % 12 + 1;
  1523.     return DSTcorrect(Start,
  1524.         Convert(Month, (time_t)tm->tm_mday, Year,
  1525.         (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
  1526.         MER24, DSTmaybe));
  1527. }
  1528.  
  1529.  
  1530. static int
  1531. LookupWord(buff)
  1532.     char        *buff;
  1533. {
  1534.     register char    *p;
  1535.     register char    *q;
  1536.     register TABLE    *tp;
  1537.     int            i;
  1538.     int            abbrev;
  1539.  
  1540.     /* Make it lowercase. */
  1541.     for (p = buff; *p; p++)
  1542.     if (isupper(*p))
  1543.         *p = tolower(*p);
  1544.  
  1545.     if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
  1546.     yylval.Meridian = MERam;
  1547.     return tMERIDIAN;
  1548.     }
  1549.     if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
  1550.     yylval.Meridian = MERpm;
  1551.     return tMERIDIAN;
  1552.     }
  1553.  
  1554.     /* See if we have an abbreviation for a month. */
  1555.     if (strlen(buff) == 3)
  1556.     abbrev = 1;
  1557.     else if (strlen(buff) == 4 && buff[3] == '.') {
  1558.     abbrev = 1;
  1559.     buff[3] = '\0';
  1560.     }
  1561.     else
  1562.     abbrev = 0;
  1563.  
  1564.     for (tp = MonthDayTable; tp->name; tp++) {
  1565.     if (abbrev) {
  1566.         if (strncmp(buff, tp->name, 3) == 0) {
  1567.         yylval.Number = tp->value;
  1568.         return tp->type;
  1569.         }
  1570.     }
  1571.     else if (strcmp(buff, tp->name) == 0) {
  1572.         yylval.Number = tp->value;
  1573.         return tp->type;
  1574.     }
  1575.     }
  1576.  
  1577.     for (tp = TimezoneTable; tp->name; tp++)
  1578.     if (strcmp(buff, tp->name) == 0) {
  1579.         yylval.Number = tp->value;
  1580.         return tp->type;
  1581.     }
  1582.  
  1583.     if (strcmp(buff, "dst") == 0) 
  1584.     return tDST;
  1585.  
  1586.     for (tp = UnitsTable; tp->name; tp++)
  1587.     if (strcmp(buff, tp->name) == 0) {
  1588.         yylval.Number = tp->value;
  1589.         return tp->type;
  1590.     }
  1591.  
  1592.     /* Strip off any plural and try the units table again. */
  1593.     i = strlen(buff) - 1;
  1594.     if (buff[i] == 's') {
  1595.     buff[i] = '\0';
  1596.     for (tp = UnitsTable; tp->name; tp++)
  1597.         if (strcmp(buff, tp->name) == 0) {
  1598.         yylval.Number = tp->value;
  1599.         return tp->type;
  1600.         }
  1601.     buff[i] = 's';        /* Put back for "this" in OtherTable. */
  1602.     }
  1603.  
  1604.     for (tp = OtherTable; tp->name; tp++)
  1605.     if (strcmp(buff, tp->name) == 0) {
  1606.         yylval.Number = tp->value;
  1607.         return tp->type;
  1608.     }
  1609.  
  1610.     /* Military timezones. */
  1611.     if (buff[1] == '\0' && isalpha(*buff)) {
  1612.     for (tp = MilitaryTable; tp->name; tp++)
  1613.         if (strcmp(buff, tp->name) == 0) {
  1614.         yylval.Number = tp->value;
  1615.         return tp->type;
  1616.         }
  1617.     }
  1618.  
  1619.     /* Drop out any periods and try the timezone table again. */
  1620.     for (i = 0, p = q = buff; *q; q++)
  1621.     if (*q != '.')
  1622.         *p++ = *q;
  1623.     else
  1624.         i++;
  1625.     *p = '\0';
  1626.     if (i)
  1627.     for (tp = TimezoneTable; tp->name; tp++)
  1628.         if (strcmp(buff, tp->name) == 0) {
  1629.         yylval.Number = tp->value;
  1630.         return tp->type;
  1631.         }
  1632.  
  1633.     return tID;
  1634. }
  1635.  
  1636.  
  1637. int
  1638. yylex()
  1639. {
  1640.     register char    c;
  1641.     register char    *p;
  1642.     char        buff[20];
  1643.     int            Count;
  1644.     int            sign;
  1645.  
  1646.     for ( ; ; ) {
  1647.     while (isspace(*yyInput))
  1648.         yyInput++;
  1649.  
  1650.     if (isdigit(c = *yyInput) || c == '-' || c == '+') {
  1651.         if (c == '-' || c == '+') {
  1652.         sign = c == '-' ? -1 : 1;
  1653.         if (!isdigit(*++yyInput))
  1654.             /* skip the '-' sign */
  1655.             continue;
  1656.         }
  1657.         else
  1658.         sign = 0;
  1659.         for (yylval.Number = 0; isdigit(c = *yyInput++); )
  1660.         yylval.Number = 10 * yylval.Number + c - '0';
  1661.         yyInput--;
  1662.         if (sign < 0)
  1663.         yylval.Number = -yylval.Number;
  1664.         return sign ? tSNUMBER : tUNUMBER;
  1665.     }
  1666.     if (isalpha(c)) {
  1667.         for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
  1668.         if (p < &buff[sizeof buff - 1])
  1669.             *p++ = c;
  1670.         *p = '\0';
  1671.         yyInput--;
  1672.         return LookupWord(buff);
  1673.     }
  1674.     if (c != '(')
  1675.         return *yyInput++;
  1676.     Count = 0;
  1677.     do {
  1678.         c = *yyInput++;
  1679.         if (c == '\0')
  1680.         return c;
  1681.         if (c == '(')
  1682.         Count++;
  1683.         else if (c == ')')
  1684.         Count--;
  1685.     } while (Count > 0);
  1686.     }
  1687. }
  1688.  
  1689.  
  1690. time_t
  1691. get_date(p, now)
  1692.     char        *p;
  1693.     struct timeb    *now;
  1694. {
  1695.     struct tm        *tm;
  1696.     struct timeb    ftz;
  1697.     time_t        Start;
  1698.     time_t        tod;
  1699. #if    !defined(HAVE_FTIME)
  1700.     extern time_t    timezone;
  1701. #endif    
  1702.  
  1703.     yyInput = p;
  1704.     if (now == NULL) {
  1705.     now = &ftz;
  1706. #if    !defined(HAVE_FTIME)
  1707.     (void)time(&ftz.time);
  1708.     /* Set the timezone global. */
  1709.     tzset();
  1710. #if sgi
  1711.     ftz.timezone = (int) _timezone / 60;
  1712. #else
  1713.     ftz.timezone = (int) timezone / 60;
  1714. #endif    
  1715. #else
  1716.     (void)ftime(&ftz);
  1717. #endif    /* HAVE_FTIME */
  1718.     }
  1719.  
  1720.     tm = localtime(&now->time);
  1721.     yyYear = tm->tm_year;
  1722.     yyMonth = tm->tm_mon + 1;
  1723.     yyDay = tm->tm_mday;
  1724.     yyTimezone = now->timezone;
  1725.     yyDSTmode = DSTmaybe;
  1726.     yyHour = 0;
  1727.     yyMinutes = 0;
  1728.     yySeconds = 0;
  1729.     yyMeridian = MER24;
  1730.     yyRelSeconds = 0;
  1731.     yyRelMonth = 0;
  1732.     yyHaveDate = 0;
  1733.     yyHaveDay = 0;
  1734.     yyHaveRel = 0;
  1735.     yyHaveTime = 0;
  1736.     yyHaveZone = 0;
  1737.  
  1738.     if (yyparse()
  1739.      || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
  1740.     return -1;
  1741.  
  1742.     if (yyHaveDate || yyHaveTime || yyHaveDay) {
  1743.     Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
  1744.             yyMeridian, yyDSTmode);
  1745.     if (Start < 0)
  1746.         return -1;
  1747.     }
  1748.     else {
  1749.     Start = now->time;
  1750.     if (!yyHaveRel)
  1751.         Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
  1752.     }
  1753.  
  1754.     Start += yyRelSeconds;
  1755.     Start += RelativeMonth(Start, yyRelMonth);
  1756.  
  1757.     if (yyHaveDay && !yyHaveDate) {
  1758.     tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
  1759.     Start += tod;
  1760.     }
  1761.  
  1762.     /* Have to do *something* with a legitimate -1 so it's distinguishable
  1763.      * from the error return value.  (Alternately could set errno on error.) */
  1764.     return Start == -1 ? 0 : Start;
  1765. }
  1766.  
  1767.  
  1768. #if    defined(TEST)
  1769.  
  1770. /* ARGSUSED */
  1771. main(ac, av)
  1772.     int        ac;
  1773.     char    *av[];
  1774. {
  1775.     char    buff[128];
  1776.     time_t    d;
  1777.  
  1778.     (void)printf("Enter date, or blank line to exit.\n\t> ");
  1779.     (void)fflush(stdout);
  1780.     while (gets(buff) && buff[0]) {
  1781.     d = get_date(buff, (struct timeb *)NULL);
  1782.     if (d == -1)
  1783.         (void)printf("Bad format - couldn't convert.\n");
  1784.     else
  1785.         (void)printf("%s", ctime(&d));
  1786.     (void)printf("\t> ");
  1787.     (void)fflush(stdout);
  1788.     }
  1789.     exit(0);
  1790.     /* NOTREACHED */
  1791. }
  1792. #endif    /* defined(TEST) */
  1793.